package com.example.jwt.main.utils;/*
 * 功能概要：字符串实用类
 *
 * [变更履历]
 * 2015年4月12日 上研院 程元森 新建
 *
 */


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

/**
 * 功能概要：字符串实用类<br>
 *
 * @author 上研院 程元森
 *
 */
public final class StringUtil {

    /**
     * 禁止实例化
     */
    private StringUtil() {
    };

    /**
     * 是否是手机号组成的字符串（多手机中间可以用半角逗号或半角分好分割 ）<br>
     *
     * @param str 验证字符串
     * @return boolean
     */
    public static boolean isPhoneNum(String str) {
        if (isBlank(str)) {
            return false;
        }
        String tmp = str.trim().replaceAll(",", "");
        tmp = tmp.replaceAll(";", "");
        return isNumeric(tmp);
    }

    /**
     * 参数为null或者长度=0时，返回true；否则false
     *
     * @param str 参数
     * @return boolean 返回
     */
    public static boolean isEmpty(String str) {
        return str == null || str.trim().length() == 0;
    }

    /**
     * 参数为null时返回空白
     *
     * @param str 参数
     * @return String 返回
     */
    public static String toEmpty(String str) {
        return str == null ? "" : str;
    }

    /**
     * 参数为null时返回空白
     *
     * @param str 参数
     * @return String 返回
     */
    public static String toEmptyObject(Object str) {
        return str == null ? "" : str + "";
    }

    /**
     * 参数为null时返回空白
     *
     * @type 需要转换的类型
     * @param str 参数
     * @return String 返回
     */
    public static String toEmptyBasic(String str) {
        return str == null ? "0" : str;
    }

    /**
     *
     * [参数为null 返回BigDecimal类型的值0]<br>
     *
     * @param object 参数
     * @return BigDecimal 返回值
     */
    public static BigDecimal getDecimal(Object object) {
        return object == null ? new BigDecimal(0) : (BigDecimal) object;
    }

    /**
     *
     * [参数为null 返回BigDecimal类型的值0]<br>
     *
     * @param object 参数
     * @return BigDecimal 返回值
     */
    public static BigDecimal getNewDecimal(Object object) {
        return object == null ? new BigDecimal(0) : new BigDecimal(object + "");
    }

    /**
     * trim参数，null时返回blank
     *
     * @param str 参数
     * @return String 返回
     */
    public static String trim(String str) {
        return str == null ? "" : str.trim();
    }

    /**
     * [方法的处理概要]<br>
     *
     * @param str 参数
     * @return 返回
     */
    public static boolean isBlank(String str) {
        return str == null || str.trim().length() == 0 || "null".equalsIgnoreCase(str.trim().toLowerCase());
    }

    /**
     * [方法的处理概要]<br>
     *
     * @param str 字符参数
     * @return 返回boolean
     */
    public static boolean isNotBlank(String str) {
        return !isBlank(str);
    }

    /**
     * 取子字符串 <br>
     * 字符串是null或者""的时候，返回"" <br>
     * 开始截取位置比字符串大时，返回"" <br>
     *
     * @param argInput 字符串
     * @param posStart 开始截取位置
     * @param posEnd 终了截取位置
     * @return 截取字符串
     */
    public static String subString(String argInput, int posStart, int posEnd) {
        if (isEmpty(argInput)) {
            return "";
        }
        int len = argInput.length();

        if (posStart < 0) {
            posStart = 0;
        }

        if (posEnd < posStart || posStart > len - 1) {
            return "";
        }

        if (posEnd > len) {
            return argInput.substring(posStart);
        }

        return argInput.substring(posStart, posEnd);
    }

    /**
     * 指定字符串是否是ip(仅限于纯粹的ip，不能带端口号）<br>
     *
     * @param ip ip
     * @return boolean
     */
    public static boolean isIP(String ip) {
        if (isEmpty(ip) || ip.length() < 7 || ip.length() > 15) {
            return false;
        }
        /**
         * 判断IP格式和范围
         */
        String rexp = "([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}";
        Pattern pat = Pattern.compile(rexp);
        Matcher mat = pat.matcher(ip);
        boolean ipAddress = mat.find();

        return ipAddress;
    }

    /**
     * 验证输入手机号码
     *
     * @param str 待验证的字符串
     * @return 如果是符合格式的字符串,返回 <b>true </b>,否则为 <b>false </b>
     */
    public static boolean isHandset(String str) {
        String regex = "^((13[0-9])|(14[0-9])|(15[0-9])|(17[0-9])|(18[0-9])|(166)|(198)|(199))\\d{8}$";
        return match(regex, str);
    }

    /**
     * 过滤非法字符
     *
     * @param str 待验证的字符串
     * @return 如果是符合格式的字符串,返回 <b>true </b>,否则为 <b>false </b>
     */
    public static boolean stringFilter(String str) {

        String regex = "[^'\\-;&#]+"; // [^?!@#$%\\^&*()]+
        return match(regex, str);
    }

    /**
     * as
     *
     * @param regex 正则表达式字符串
     * @param str 要匹配的字符串
     * @return 如果str 符合 regex的正则表达式格式,返回true, 否则返回 false;
     */
    public static boolean match(String regex, String str) {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(str);
        return matcher.matches();
    }

    /**
     * 是否是纯数字组成的字符串<br>
     *
     * @param str 验证字符串
     * @return boolean
     */
    public static boolean isNumeric(String str) {
        if (isBlank(str)) {
            return false;
        }
        return str.matches("^[0-9]*$");
    }

    /**
     * 字符串的压缩
     *
     * @param str 待压缩的字符串
     * @return 返回压缩后的字符串
     * @throws IOException 异常
     */
    public static String compress(String str) throws IOException {
        if (org.apache.commons.lang3.StringUtils.isBlank(str)) {
            return str;
        }
        // 创建一个新的输出流
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        // 使用默认缓冲区大小创建新的输出流
        GZIPOutputStream gzip = new GZIPOutputStream(out);
        // 将字节写入此输出流
        gzip.write(str.getBytes("utf-8")); // 因为后台默认字符集有可能是GBK字符集，所以此处需指定一个字符集
        gzip.close();
        // 使用指定的 charsetName，通过解码字节将缓冲区内容转换为字符串
        return out.toString("ISO-8859-1");
    }

    /**
     * 字符串的解压
     *
     * @param str 对字符串解压
     * @return 返回解压缩后的字符串
     * @throws IOException 异常
     */
    public static String unCompress(String str) throws IOException {
        if (org.apache.commons.lang3.StringUtils.isBlank(str)) {
            return str;
        }
        // 创建一个新的输出流
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        // 创建一个 ByteArrayInputStream，使用 buf 作为其缓冲区数组
        ByteArrayInputStream in = new ByteArrayInputStream(str.getBytes("ISO-8859-1"));
        // 使用默认缓冲区大小创建新的输入流
        GZIPInputStream gzip = new GZIPInputStream(in);
        byte[] buffer = new byte[256];
        int n = 0;

        // 将未压缩数据读入字节数组
        while ((n = gzip.read(buffer)) >= 0) {
            out.write(buffer, 0, n);
        }
        // 使用指定的 charsetName，通过解码字节将缓冲区内容转换为字符串
        return out.toString("utf-8");
    }

    /**
     * [时间格式化]<br>
     *
     * @param happenTime2 happenTime2
     * @return String
     */
    public static String dateUt(Date happenTime2) {
        if (happenTime2 != null) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            // SimpleDateFormat sdf = new
            // SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
            return sdf.format(happenTime2);
        }
        return "";
    }

    /**
     * [时间转换]<br>
     *
     * @param happenTime2 happenTime2
     * @return Date
     */
    public static Date dateTr(String happenTime2) {
        if (happenTime2 != null) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            // SimpleDateFormat sdf = new
            // SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
            try {
                return sdf.parse(happenTime2);
            } catch (ParseException e) {
                return null;
            }
        }
        return null;
    }

    /**
     * [String转list]<br>
     *
     * @param chkIdAryStr chkIdAryStr
     * @return List<String> List<String>
     */
    public static List<String> toList(String chkIdAryStr) {
        List<String> list = new ArrayList<String>();
        if (chkIdAryStr != null && !"".equals(chkIdAryStr.trim())) {
            String[] ary = chkIdAryStr.split(",");
            if (ary != null && ary.length > 0) {
                for (String s : ary) {
                    list.add(s);
                }
            }
        }
        return list;
    }

    /**
     * 替换敏感字符<br>
     *
     * @param string 非法字符
     * @return 替换后的合法字符
     */
    public static String cleanXSS(String string) {
        if (string != null) {
            string = string.replaceAll(CommonConst.ILLEGAL_CHAR1, CommonConst.CH_ILLEGAL_CHAR1)
                    .replaceAll(CommonConst.ILLEGAL_CHAR2, CommonConst.CH_ILLEGAL_CHAR2)
                    .replaceAll(CommonConst.ILLEGAL_CHAR3, CommonConst.CH_ILLEGAL_CHAR3)
                    .replaceAll(CommonConst.ILLEGAL_CHAR4, CommonConst.CH_ILLEGAL_CHAR4)
                    .replaceAll(CommonConst.ILLEGAL_CHAR5, CommonConst.CH_ILLEGAL_CHAR5)
                    .replaceAll(CommonConst.LT, CommonConst.LTC).replaceAll(CommonConst.GT, CommonConst.GTC)
                    .replaceAll(CommonConst.QUOT, CommonConst.QUOTC);
        }
        return string;
    }

    /**
     * 是否有存储型XSS敏感字符
     * @param string string
     * @return 是否不合规
     */
    public static boolean hasIllegalCharForXSS(String string) {
        String regex = String.format("[\\s\\S]*(%s|%s|%s|%s|%s|%s|%s|%s)+[\\s\\S]*", CommonConst.ILLEGAL_CHAR1, CommonConst.ILLEGAL_CHAR2, CommonConst.ILLEGAL_CHAR3,
                CommonConst.ILLEGAL_CHAR4, CommonConst.ILLEGAL_CHAR5, CommonConst.LT, CommonConst.GT, CommonConst.QUOT);
        return match(regex, string);
    }

    /**
     * 判断是否为合规的header内容
     * @param content header内容
     * @return 是否合规
     */
    public static boolean isLegalHeaderContent(String content) {
        return !isIllegalHeaderContent(content);
    }

    /**
     * 判断是否为合规的header内容
     * @param content header内容
     * @return 是否合规
     */
    public static boolean isIllegalHeaderContent(String content) {
        String regex = "[\\s\\S]*(200\\n|200\\r|OK\\n|OK\\r|\\n|\\r)+[\\s\\S]*";
        return match(regex, content);
    }

    /**
     * 返回合规的header内容，不合规则抛出异常
     * @param content header内容
     * @return 合规的header内容
     */
    public static String legalHeaderContent(String content) throws Exception {
        if (isIllegalHeaderContent(content)) {
            throw new IllegalArgumentException("HTTP header content can not contain sensitive words like \"\\n\" \"\\r\" \"OK\" \"200\"");
        }
        return content;
    }

    /**
     * 路径是否合规
     * @param filePath 文件路径
     * @return 是否合规
     */
    public static boolean isLegalFilePath(String filePath) {
        return !isIllegalFilePath(filePath);
    }

    /**
     * 路径是否不合规
     * @param filePath 文件路径
     * @return 是否不合规
     */
    public static boolean isIllegalFilePath(String filePath) {
        String regex = "[\\s\\S]*(\\.{2}|~|\\./|\\.{2}/|~/)+[\\s\\S]*";
        return match(regex, filePath);
    }

    /**
     * 返回合规的文件路径，不合规则抛出异常
     * @param filePath 文件路径
     * @return 合规的文件路径
     */
    public static String legalFilePath(String filePath) throws Exception {
        if (isIllegalFilePath(filePath)) {
            throw new IllegalArgumentException("filePath can not include sensitive characters like \"~\", \"..\", \"./\", \"../\", \"~/\"");
        }
        return filePath;
    }
}
